package it.polimi.swKnights.SWIMv2.ejb.personalData;

import it.polimi.swKnights.SWIMv2.ejb.authentication.LoginHandlerLocal;
import it.polimi.swKnights.SWIMv2.ejb.entityBeans.RegisteredUser;
import it.polimi.swKnights.SWIMv2.ejb.entityBeans.ToConfirmUser;
import it.polimi.swKnights.SWIMv2.ejb.exceptions.InvalidLoginPrivilegesException;
import it.polimi.swKnights.SWIMv2.ejb.exceptions.LoginFailException;
import it.polimi.swKnights.SWIMv2.ejb.friendsEngine.FriendshipManagerLocal;
import it.polimi.swKnights.SWIMv2.ejb.searchEngine.ResultCategory;

import java.util.Calendar;
import java.util.Date;
import java.util.Map;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 * Session Bean implementation class UserFinder
 */
@Stateless
public class UserFinder implements UserFinderRemote, UserFinderLocal
{

	@PersistenceContext(unitName = "swimv2-manager")
	private EntityManager manager;

	@EJB
	private LoginHandlerLocal loginController;

	@EJB
	private PersonalDataManagerLocal dataManager;

	@EJB
	private FriendshipManagerLocal friendshipManagerLocal;

	/**
	 * if a user does exist this method will return true. False otherwise
	 */
	@Override
	public boolean existingUserName(String userName)
	{
		RegisteredUser user = this.manager.find(RegisteredUser.class, userName);

		if (user != null)
		{
			return true;
		}
		else
		{
			return this.isReserved(userName);
		}
	}

	/**
	 * returns null if something went wrong with the login values, the user map
	 * otherwise
	 * 
	 * @param userName
	 * @param password
	 * @return
	 * @throws InvalidLoginPrivilegesException
	 * @throws LoginFailException
	 */
	@Override
	public Map<String, String> getUserRefereces(String userName,
			String password, String userToGet) throws LoginFailException,
			InvalidLoginPrivilegesException
	{
		this.loginController.checkLoginDataAndPrivileges(userName, password,
				RegisteredUser.class);

		RegisteredUser user = manager.getReference(RegisteredUser.class,
				userToGet);

		return this.dataManager.getUserDataMap(user,
				this.isFriend(userName, userToGet));
	}

	@Override
	public Map<String, String> getUserRefereces(String userName)
	{
		RegisteredUser user = manager.getReference(RegisteredUser.class,
				userName);

		return this.dataManager.getUserDataMap(user, null);
	}

	@Override
	public boolean isPublicUser(String userName)
	{
		RegisteredUser user = this.manager.find(RegisteredUser.class, userName);
		if (user != null)
		{
			return user.isPublic();
		}
		else
		{
			return false;
		}
	}

	private ResultCategory isFriend(String userName, String userToGet)
	{
		if (userName.equals(userToGet))
		{
			return ResultCategory.myself;
		}
		else if (this.friendshipManagerLocal.areFriend(userName, userToGet))
		{
			return ResultCategory.friend;
		}
		else
		{
			return null;
		}
	}

	private boolean isReserved(String userName)
	{
		ToConfirmUser toConfirm = this.manager.find(ToConfirmUser.class,
				userName);
		if (toConfirm != null)
		{
			return isExpiredExistentToConfirmedUser(toConfirm);
		}
		else
		{
			return userName.equals("guest");
		}
	}

	private boolean isExpiredExistentToConfirmedUser(ToConfirmUser toConfirm)
	{
		Date expirationDate = toConfirm.getValidUntil();
		if (Calendar.getInstance().after(expirationDate))
		{
			this.manager.remove(toConfirm);
			return true;
		}
		else
		{
			return false;
		}
	}

}
